package com.rlz.lib_so;

import android.annotation.SuppressLint;
import android.app.Application;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Message;
import android.util.Log;


import java.io.File;
import java.io.IOException;
import java.lang.ref.WeakReference;

import androidx.annotation.NonNull;

/**
 * Created by RLZ
 * on 2021/5/11
 * <p>
 * so文件下载管理
 */
public class SoDownload implements SoLoad.LoadCallback, Handler.Callback {

    private DownloadManager mDownloadManager;

    @SuppressLint("StaticFieldLeak")
    private static Context mContext;

    private long mDownloadId;

    private Callback mCallback;

    private static boolean isInstallTXSDK;

    private static final int MSG_WHAT = 0x1001;

    private IDownloadDialog mDialog; //不设置dialog不使用

    private Handler mHandler;

    private QueryRunnable mQueryRunnable;

    private String mMatchName;
    /**
     * 需要拷贝的文件目录
     */
    public static String SO_ZIP_PATH;


    public static void init(Context context) {
        mContext = new WeakReference<>(context.getApplicationContext()).get();
    }

    /**
     * 下载SO文件
     *
     * @param matchName 需要下载的SO文件类型 必传参数需要比对SO文件的加载状态
     * @param url       SO文件下载地址
     * @param dirType   SO文件目录类型
     * @param fileName  SO文件的名称
     */
    public void download(@SoType String matchName, String url, String dirType, String fileName) {
        mMatchName = matchName;

        if (mContext == null) throw new ExceptionInInitializerError("请先初始化 init()");

        if (!(mContext instanceof Application)) Log.e("", "这个context 请使用application的");

        SO_ZIP_PATH = mContext.getExternalFilesDir(matchName)
                + File.separator + "lib";
        downloadFile(url, dirType, fileName);
    }

    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            updateStatus();
        }
    };


    @Override
    public boolean handleMessage(@NonNull Message msg) {
        if (msg.what == MSG_WHAT) {
            if (isDisplay()) {
                mDialog.progress(msg.arg1);
                mDialog.max(msg.arg2);
            }
        }
        return false;
    }


    //安卓Q后 通过getExternalFilesDir来设置文件路劲
    private void downloadFile(String url, String dirType, String fileName) {

        //需要对文件校验
        File file = new File(mContext.getExternalFilesDir(null),
                dirType + File.separator + fileName);
        if (file.exists()) {
            //如果so文件已经下载过 直接copy
            copyAndLoad(file);
            return;
        }

        clearFile(dirType);

        DownloadManager.Request rt = new DownloadManager.Request(Uri.parse(url));
        rt.setAllowedOverRoaming(false);
        rt.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI
                | DownloadManager.Request.NETWORK_MOBILE);

        rt.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);

        rt.setDestinationInExternalFilesDir(mContext, dirType, fileName);
        if (mDownloadManager == null)
            mDownloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);

        mDownloadId = mDownloadManager.enqueue(rt);

        mContext.registerReceiver(mReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

        if (isDisplay())
            if (mHandler == null) {
                mHandler = new Handler(this);
                mQueryRunnable = new QueryRunnable();
                startQuery();
            }
    }

    private void clearFile(String dirType) {
        //清空之前的下载
        new Thread() {
            @Override
            public void run() {
                super.run();
                deleteDirAndFile(new File(mContext.getExternalFilesDir(null), dirType));
                deleteDirAndFile(new File(SO_ZIP_PATH));
            }
        }.start();
    }


    //检查下载状态
    private void updateStatus() {
        if (mDownloadId == 0) return;
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(mDownloadId);
        Cursor cursor = mDownloadManager.query(query);
        if (cursor == null) return;
        if (!cursor.moveToFirst()) {
            if (!cursor.isClosed()) cursor.close();
            return;
        }
        int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
        switch (status) {

            //下载完成
            case DownloadManager.STATUS_SUCCESSFUL:
                complete(cursor);
                break;


            //下载失败
            case DownloadManager.STATUS_FAILED:
                fail(cursor);
                break;
        }

    }

    private void fail(Cursor cursor) {
        if (!cursor.isClosed()) cursor.close();

        if (isDisplay()) mDialog.dismiss();

        if (mCallback != null) mCallback.onFailed(new Error("文件下载失败,请重试"));

        mContext.unregisterReceiver(mReceiver);

        stopQuery();

        removeDownload();
    }

    private void complete(Cursor cursor) {
        if (!cursor.isClosed()) cursor.close();

        if (isDisplay()) mDialog.dismiss();

        copyAndLoad(null);

        stopQuery();
    }


    private class QueryRunnable implements Runnable {

        @Override
        public void run() {
            querySchedule();
            mHandler.postDelayed(mQueryRunnable, 60);
        }
    }

    private void querySchedule() {
        // 查询下载情况
        Cursor cursor = mDownloadManager.query(new DownloadManager.Query().setFilterById(mDownloadId));
        if (cursor == null) return;
        if (!cursor.moveToFirst()) {
            if (!cursor.isClosed()) cursor.close();
            return;
        }
        int byteDownload = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
        int totalSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
        Message msg = Message.obtain();
        if (totalSize > 0) {
            msg.what = MSG_WHAT;
            msg.arg1 = byteDownload;
            msg.arg2 = totalSize;
            mHandler.sendMessage(msg);
        }
        if (!cursor.isClosed()) cursor.close();
    }


    //开始查询
    private void startQuery() {
        if (mDownloadId != 0) {
            mDialog.show();
            mHandler.post(mQueryRunnable);
        }
    }

    //停止查询
    private void stopQuery() {
        if (isDisplay())
            mHandler.removeCallbacks(mQueryRunnable);
    }

    //下载停止同时删除下载文件
    private void removeDownload() {
        if (mDownloadManager != null) mDownloadManager.remove(mDownloadId);
    }


    //检验下载完或者之前下载过 通过null来区分
    private void copyAndLoad(File file) {
        try {

            ZipHelper.upZip(file == null ? getTargetFile() : file);

            SoLoad.loadSoFile(mMatchName, SoDownload.this);

            if (isDisplay()) mDialog.dismiss();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取当前下载完成的文件
     */
    private File getTargetFile() {
        File targetFile = null;
        if (mDownloadId != -1) {
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(mDownloadId);
            query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
            Cursor cur = mDownloadManager.query(query);
            if (cur != null) {
                if (cur.moveToFirst()) {
                    String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                    if (!uriString.isEmpty()) {
                        targetFile = new File(Uri.parse(uriString).getPath());
                    }
                }
                cur.close();
                mDownloadId = -1;
            }
        }
        return targetFile;
    }


    public void destroy() {
        if (mHandler != null) {
            mHandler.removeCallbacksAndMessages(null);
        }
        mContext.unregisterReceiver(mReceiver);

        mCallback = null;

        if (isDisplay())
            mDialog.onDetachedFromWindow();
    }

    @Override
    public void onSuccess() {
        /*if (!isInstallTXSDK) {
            TXLiveBase.getInstance().setLicence(LiveApp.getInstance(),
                    TCConstants.VOD_LICENSE_URL, TCConstants.VOD_APPKEY);
            isInstallTXSDK = true;
        }*/

        if (mCallback != null) mCallback.onSuccess();

    }

    @Override
    public void onFailed() {
        if (mCallback != null)
            mCallback.onFailed(new Error("文件加载失败,请重试"));
    }

    public interface Callback {

        void onSuccess();

        void onFailed(Error error);
    }

    public void callback(Callback callback) {
        mCallback = callback;
    }

    public void dialog(IDownloadDialog dialog) {
        mDialog = dialog;
    }

    private boolean isDisplay() {
        return mDialog != null;
    }

    public static Context getContext() {
        return mContext;
    }

    private void deleteDirAndFile(File file) {
        if (file == null || !file.exists()) return;
        if (file.isDirectory()) {
            for (File f : file.listFiles()) {
                if (f.isFile()) {
                    f.delete();
                } else if (f.isDirectory()) {
                    deleteDirAndFile(f);
                }
            }
        }
        file.delete();
    }
}

